#ifndef POINT_2D_H
#define POINT_2D_H
#define SQR(X) ((X)*(X))

#include <math.h>
#include "../util/NTuple.h"
namespace geom
{
    /** Class that handles data and operations related to points in a 3D space */
    class Point2D
    {
        public:
            union{
                struct
                {
                    float x,y;
                };
                float v[2];
            };

            /** Computes the distance between this point and another
              @param p The point to calculate the distance to
              \return Distance from this point to p */
            inline float distance (const Point2D &p) const{return sqrtf(distanceSquared(p));}

            /** Computes the square of the distance to the point p. This is
              here only for performance reasons (distance requires an sqrt op,
              which can be too much of an overhead for cpu-intensive ops
              @param p Point to calculate the square of the distance
              \return Square of the distance to p */
            inline float distanceSquared(const Point2D &p) const {return ( SQR(x-p.x) + SQR(y-p.y) );}
            /** Default constructor. Creates a Point2D with coordinates (0,0)*/
            Point2D();
            /** Constructor with specified coordinates */
            Point2D(float px, float py);
            /** Constructor with specified coordinates given as a 2 floats array
              @param pv Memory address of an array with 3 floats */
            Point2D(const float * pv);
              
            /** Checks if this point is equal to the given one
              @param p Point to compare to
              \note There is a small threshold to check for equality, not
              bigger than 1e-06, so slightly different points can be considered
              equal. Note that as Point2D uses floating point values internally,
              this value cannot be trusted for sufficiently big values. For example, 
              these two pieces of code return different values:
                \code 
                float a = 1000.0;
                float b = 1000.0+1e-05;
                return (a == b) // this returns true
                \endcode
                \code
                float a = 100.0;
                float b = 100.0+1e-05;
                return (a == b) // this returns false
                \endcode 
             */
			bool operator==(const Point2D & p) const
			{ return distanceSquared(p) < SQR(1e-07);}
            
            /** The reverse operation of '=='. Check operator== doc for details */
            bool operator!=(const Point2D & p) const {return !((*this)==p);}

			/** Assigns a point value to this one */
			Point2D & operator=(const Point2D &p){x=p.x;y=p.y;return *this;}
			/** Assigns a point value to this one, from a Triplet<float> */
			Point2D & operator=(const util::Pair<float> &p){x=p[0];y=p[1]; return *this;}
    };
}

#endif
